﻿using System;
using System.Linq;
using ZSZ.Application.IService;
using ZSZ.Common;
using ZSZ.Core.Entities;
using ZSZ.DTO;
using ZSZ.EntityFramework;

namespace ZSZ.Application.Service
{
    public class UserService : Repository<UserEntity>, IUserService
    {
        public long AddNew(string phoneNum, string password)
        {
            //检查手机号不能重复
            bool exists = GetAllDataEntity().Any(u => u.PhoneNum == phoneNum);
            if (exists)
            {
                throw new ArgumentException("手机号已经存在");
            }
            string salt = CommonHelper.CreateVerifyCode(5);
            string pwdHash = CommonHelper.CalcMD5(salt + password);
            var user = new UserEntity
            {
                PhoneNum = phoneNum,
                PasswordHash = pwdHash,
                PasswordSalt = salt
            };
            SaveOrUpdate(user,true);
            return user.Id;
        }

        public bool CheckLogin(string phoneNum, string password)
        {
            var user = GetAllDataEntity().SingleOrDefault(u=>u.PhoneNum==phoneNum);
            if(user==null)
            {
                return false;
            }
            else
            {
                string dbPwdHash = user.PasswordHash;
                string salt = user.PasswordSalt;
                string userPwdHash = CommonHelper.CalcMD5(salt + password);
                return dbPwdHash == userPwdHash;
            }
        }

        private UserDTO ToDTO(UserEntity user)
        {
            var dto = new UserDTO
            {
                CityId = user.CityId,
                CreateDateTime = user.CreateDateTime,
                Id = user.Id,
                LastLoginErrorDateTime = user.LastLoginErrorDateTime,
                LoginErrorTimes = user.LoginErrorTimes,
                PhoneNum = user.PhoneNum
            };
            return dto;
        }

        public UserDTO GetById(long id)
        {
            var user = GetOneById(id);
            return user == null ? null : ToDTO(user);
        }

        public UserDTO GetByPhoneNum(string phoneNum)
        {
            var user = GetAllDataEntity().SingleOrDefault(u => u.PhoneNum == phoneNum);
            return user == null ? null : ToDTO(user);
        }

        public void SetUserCityId(long userId, long cityId)
        {
           
            var user = GetOneById(userId);
            if(user==null)
            {
                throw new ArgumentException("用户id不存在"+userId);
            }
            user.CityId = cityId;
            SaveOrUpdate(user,false);
            
        }

        public void UpdatePwd(long userId, string newPassword)
        {
            //检查手机号不能重复
            var user = GetOneById(userId);
            if (user==null)
            {
                throw new ArgumentException("用户不存在 "+ userId);
            }
            string salt = user.PasswordSalt;      // CommonHelper.CreateVerifyCode(5);
            string pwdHash = CommonHelper.CalcMD5(salt + newPassword);
            user.PasswordHash = pwdHash;
            user.PasswordSalt = salt;
            SaveOrUpdate(user,false);
        }

        public void IncrLoginError(long id)
        {
            //检查手机号不能重复
            var user = GetOneById(id);
            if (user == null)
            {
                throw new ArgumentException("用户不存在 " + id);
            }
            user.LoginErrorTimes++;
            user.LastLoginErrorDateTime = DateTime.Now;
            SaveOrUpdate(user,false);
        }

        public void ResetLoginError(long id)
        {
            //检查手机号不能重复
            var user = GetOneById(id);
            if (user == null)
            {
                throw new ArgumentException("用户不存在 " + id);
            }
            user.LoginErrorTimes = 0;
            user.LastLoginErrorDateTime = null;
            SaveOrUpdate(user,false);
        }

        public bool IsLocked(long id)
        {
            var user = GetById(id);
            //错误登录次数>=5，最后一次登录错误时间在30分钟之内
            return (user.LoginErrorTimes >= 5 
                && user.LastLoginErrorDateTime > DateTime.Now.AddMinutes(-30)) ;
        }

        public UserService(ZSZDbContext context) : base(context)
        {
        }
    }
}
